#include <stdio.h> // perror()
#include <stdlib.h> // exit()
#include <unistd.h> // ftruncate() / close() / fork() / sleep()
#include <fcntl.h> // pid_t / 
#include <sys/mman.h> // shm_open()/shm_unlink()/mmap()/munmap()
#include <wait.h> // wait()
#include <string.h> // strcpy()
#include <semaphore.h>

int main(int argc, char const *argv[])
{ 
//1   创建内存文件对象 shm 
    char *shm_path="shm_value";
    char *shm_sem_path="shm_sem";
    int fd = shm_open(shm_path,O_RDWR|O_CREAT,0666);
    int sem_fd = shm_open(shm_sem_path,O_RDWR|O_CREAT,0666);
    if(fd==-1)
    {
        perror("shm_open");
        exit(EXIT_FAILURE);
    }
// 2   给内存文件对象告知逻辑空间 truncate
    ftruncate(fd,1024);
    ftruncate(sem_fd,sizeof(sem_t));
    printf("sem size :%ld\n",sizeof(sem_t));
// 3   mmap 参数  :fd ,空间大小 ，权限，share, 起始偏移量0
    char *addr = mmap(NULL,1024,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
    sem_t *sem_addr = mmap(NULL,sizeof(sem_t),PROT_READ|PROT_WRITE,MAP_SHARED,sem_fd,0);
//        mmap  1 开辟内存空间2将空间映射给内存文件对象3 返回地址指针
// 4   fork 子进程
    sem_init(sem_addr,1,0);//地址 1 进程共享 模式 0 初始值
    pid_t pid = fork();
    if(pid>0)
    {// 5   父进程 
        sleep(1);
//            向地址写入数据 write  
        sprintf(addr,"1000000000$");
        printf("send something to son\n");
        sem_post(sem_addr);
//            等子进程
        waitpid(pid,NULL,0 );
    }else if (pid==0)
    {// 6   子进程 
        sem_wait(sem_addr);
//            从地址中读取数据 打印 
        printf("get something from dad:%s\n",addr);
//             退出
        _exit(EXIT_SUCCESS);
    }
// 7    释放mmap开放的内存空间
    munmap(addr,1024);
    munmap(sem_addr,sizeof(sem_t));
// 8    删除内存文件对象
    shm_unlink(shm_path);
    shm_unlink(shm_sem_path);
     
    return 0;
 
}
